/**
 * Copyright (c) 2020-2021 ThunderSoft
 * All Rights Reserved by Thunder Software Technology Co., Ltd and its affiliates.
 * You may not use, copy, distribute, modify, transmit in any form this file
 * except in compliance with ThunderSoft in writing by applicable law.
 *
 */
/**
 * @file    task.h
 * @brief   task funtion header file for freertos adapter
 * @details task funtion for freertos adapter
 * @version 1.0
 * @author  Hu lei
 * @date    2021-03-05
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2021-03-05               Hu lei              Create it.
 *
 */
#ifndef INC_TASK_H
#define INC_TASK_H

#ifndef INC_FREERTOS_H
    #error "include FreeRTOS.h must appear in source files before include task.h"
#endif

#include "list.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <cmsis_os2.h>

/*-----------------------------------------------------------
 * MACROS AND DEFINITIONS
 *----------------------------------------------------------*/
#define tskKERNEL_VERSION_NUMBER        ( "V10.2.0"  )
#define tskKERNEL_VERSION_MAJOR         ( 10         )
#define tskKERNEL_VERSION_MINOR         ( 2          )
#define tskKERNEL_VERSION_BUILD         ( 0          )

#define tskMPU_REGION_READ_ONLY         ( 1UL << 0UL )
#define tskMPU_REGION_READ_WRITE        ( 1UL << 1UL )
#define tskMPU_REGION_EXECUTE_NEVER     ( 1UL << 2UL )
#define tskMPU_REGION_NORMAL_MEMORY     ( 1UL << 3UL )
#define tskMPU_REGION_DEVICE_MEMORY     ( 1UL << 4UL )

typedef struct tskTaskControlBlock { 
    volatile StackType_t    *pxTopOfStack;

    #if ( portUSING_MPU_WRAPPERS == 1 )
        xMPU_SETTINGS   xMPUSettings;
    #endif

    ListItem_t          xStateListItem;
    ListItem_t          xEventListItem;
    UBaseType_t         uxPriority;    
    StackType_t         *pxStack;      
    char                pcTaskName[ configMAX_TASK_NAME_LEN ];
    #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
        StackType_t     *pxEndOfStack; 
    #endif

    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
        UBaseType_t     uxCriticalNesting;
    #endif

    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t     uxTCBNumber;      
        UBaseType_t     uxTaskNumber;     
    #endif

    #if ( configUSE_MUTEXES == 1 )
        UBaseType_t     uxBasePriority;   
        UBaseType_t     uxMutexesHeld;
    #endif

    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
        TaskHookFunction_t pxTaskTag;
    #endif

    #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
        void            *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
    #endif

    #if( configGENERATE_RUN_TIME_STATS == 1 )
        uint32_t        ulRunTimeCounter; 
    #endif

    #if ( configUSE_NEWLIB_REENTRANT == 1 )
        struct  _reent xNewLib_reent;
    #endif

    #if( configUSE_TASK_NOTIFICATIONS == 1 )
        volatile uint32_t ulNotifiedValue;
        volatile uint8_t ucNotifyState;
    #endif
    #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
        uint8_t ucStaticallyAllocated;
    #endif

    #if( INCLUDE_xTaskAbortDelay == 1 )
        uint8_t ucDelayAborted;
    #endif

    #if( configUSE_POSIX_ERRNO == 1 )
        int iTaskErrno;
    #endif

    osThreadId_t threadId;
    osSemaphoreId_t sem_id;
} tskTCB;

struct tskTaskControlBlock;
typedef struct tskTaskControlBlock* TaskHandle_t;
typedef BaseType_t (*TaskHookFunction_t)( void * );

typedef enum {
    eRunning = 0,
    eReady,
    eBlocked,
    eSuspended,
    eDeleted,
    eInvalid
} eTaskState;

typedef enum {
    eNoAction = 0,
    eSetBits, 
    eIncrement,
    eSetValueWithOverwrite,
    eSetValueWithoutOverwrite
} eNotifyAction;

typedef struct xTIME_OUT {
    BaseType_t xOverflowCount;
    TickType_t xTimeOnEntering;
} TimeOut_t;

typedef struct xMEMORY_REGION {
    void *pvBaseAddress;
    uint32_t ulLengthInBytes;
    uint32_t ulParameters;
} MemoryRegion_t;

typedef struct xTASK_PARAMETERS {
    TaskFunction_t pvTaskCode;
    const char * const pcName;
    configSTACK_DEPTH_TYPE usStackDepth;
    void *pvParameters;
    UBaseType_t uxPriority;
    StackType_t *puxStackBuffer;
    MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
    #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
        StaticTask_t * const pxTaskBuffer;
    #endif
} TaskParameters_t;

typedef struct xTASK_STATUS {
    TaskHandle_t xHandle;
    const char *pcTaskName;
    UBaseType_t xTaskNumber;
    eTaskState eCurrentState;
    UBaseType_t uxCurrentPriority;
    UBaseType_t uxBasePriority;
    uint32_t ulRunTimeCounter;
    StackType_t *pxStackBase;
    configSTACK_DEPTH_TYPE usStackHighWaterMark;
} TaskStatus_t;

typedef enum {
    eAbortSleep = 0,
    eStandardSleep,
    eNoTasksWaitingTimeout
} eSleepModeStatus;


#define taskENABLE_INTERRUPTS()     __asm volatile( "csrs mstatus, 8" )
#define tskIDLE_PRIORITY            ( ( UBaseType_t ) 0U )
#define taskSCHEDULER_SUSPENDED     ( ( BaseType_t ) 0   )
#define taskSCHEDULER_NOT_STARTED   ( ( BaseType_t ) 1   )
#define taskSCHEDULER_RUNNING       ( ( BaseType_t ) 2   )					

/*-----------------------------------------------------------
 * FUNCTION API
 *----------------------------------------------------------*/
extern void turboxYieldTask(void);
extern void turboxEnterCritical( void );
extern void turboxExitCritical( void );
extern void turboxDisableISR(void);
extern BaseType_t turboxCreateDynamicTask( TaskFunction_t, const char * const ,
                            const configSTACK_DEPTH_TYPE, void * const,
                            UBaseType_t, TaskHandle_t * const );
extern TaskHandle_t turboxCreateStaticTask( TaskFunction_t, const char * const, const unsigned int, void * const,
                                    UBaseType_t, StackType_t * const, StaticTask_t * const);
extern BaseType_t turboxAddTick( void );
extern void turboxStartScheduler( void );
extern void turboxSwitchTaskContext( void );
extern TickType_t turboxGetTickCount( void );
extern void turboxDeleteTask( TaskHandle_t  );
extern void turboxDelayTask( const TickType_t );
extern TaskHandle_t turboxGetCurrentTCB( void );
extern BaseType_t xPortIsInsideInterrupt( void );
extern void turboxTaskStepTick( const TickType_t );
extern TickType_t turboxGetTickCountFromISR( void );
extern void turboxTaskStepTickSafe( const TickType_t );
extern BaseType_t turboxClearNotifyState( TaskHandle_t );
extern uint32_t turboxTakeTaskNotify(BaseType_t, TickType_t);
extern UBaseType_t turboxGetStackHighWaterMark( TaskHandle_t );
extern BaseType_t turboxGetTickCount2( TickType_t *, BaseType_t * );
extern BaseType_t turboxWaitTaskNotify(uint32_t, uint32_t, uint32_t *, TickType_t);
extern void turboxGiveTaskNotifyFromISR( TaskHandle_t xTaskToNotify, BaseType_t * );
extern BaseType_t turboxGenericNotify( TaskHandle_t, uint32_t, eNotifyAction, uint32_t * );
extern BaseType_t turboxGenericNotifyFromISR( TaskHandle_t, uint32_t, eNotifyAction, uint32_t *, BaseType_t * );

#define taskYIELD                   turboxYieldTask
#define taskDISABLE_INTERRUPTS      turboxDisableISR
#define vTaskExitCritical           turboxExitCritical
#define taskEXIT_CRITICAL           turboxExitCritical
#define vTaskEnterCritical          turboxEnterCritical     
#define taskENTER_CRITICAL          turboxEnterCritical
#define xTaskCreate                 turboxCreateDynamicTask
#define xTaskCreateStatic           turboxCreateStaticTask
#define xTaskGetTickCount           turboxGetTickCount
#define xTaskGetTickCount2          turboxGetTickCount2
#define xTaskGetTickCountFromISR    turboxGetTickCountFromISR	
#define vTaskSwitchContext          turboxSwitchTaskContext	
#define vTaskDelete                 turboxDeleteTask			
#define vTaskDelay                  turboxDelayTask			
#define vTaskStartScheduler         turboxStartScheduler		    
#define uxTaskGetStackHighWaterMark turboxGetStackHighWaterMark 	
#define ulTaskNotifyTake            turboxTakeTaskNotify			
#define xTaskNotifyWait             turboxWaitTaskNotify			
#define xTaskGenericNotifyFromISR   turboxGenericNotifyFromISR		
#define vTaskNotifyGiveFromISR      turboxGiveTaskNotifyFromISR		
#define xTaskNotifyStateClear       turboxClearNotifyState			
#define xTaskIncrementTick          turboxAddTick				    
#define xTaskGetCurrentTaskHandle   turboxGetCurrentTCB			    
#define vTaskStepTick               turboxTaskStepTick			    
#define vTaskStepTickSafe           turboxTaskStepTickSafe
#define xTaskNotify(A, B, C)        turboxGenericNotify(A, B, C, NULL)
#define xTaskNotifyGive( A )        turboxGenericNotify( ( A ), ( 0 ), eIncrement, NULL )
#define xTaskNotifyFromISR(A, B, C, D) turboxGenericNotifyFromISR(A, B, C, NULL, D)

#ifdef __cplusplus
}
#endif
#endif /* INC_TASK_H */
